package com.better.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.better.common.base.ServiceResponse;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CmsHttpPostUtil {



    /**
     * 调用HTTPS接口的POST方法
     * @param url
     * @param charset 默认UTF-8
     * @param params
     * @return 200时返回接口返回值，否则返回"{\"errorCode\":\"错误码\"}"
     * @throws RuntimeException
     */
    public static ServiceResponse HttpsPost(String url, String charset,
                                   Map<String,String> params,String token) throws RuntimeException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = createHttpsClient();
            // 建立HttpPost对象
            HttpPost httppost = new HttpPost(url);
            if(token!=null&&!"".equals(token)){
                httppost.setHeader("Authorization",token);
            }
            // 配置要 POST 的数据begin
            List<NameValuePair> nvp = new ArrayList<NameValuePair>();
            if(params !=null && params.size()>0){
                for (Map.Entry<String, String> e: params.entrySet())
                    nvp.add(new BasicNameValuePair(e.getKey(), e.getValue()));
            }
            httppost.setEntity(new UrlEncodedFormEntity(nvp,charset));
            // 发送Post,并返回一个HttpResponse对象
            HttpResponse httpResponse = closeableHttpClient.execute(httppost);
            HttpEntity httpEntity = httpResponse.getEntity();
            // 如果状态码为200,就是正常返回
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 得到返回的字符串
                return JSONObject.parseObject(EntityUtils.toString(httpEntity),ServiceResponse.class);
                // 如果是下载文件,可以用response.getEntity().getContent()返回InputStream
            } else {
                return getErrorCodeJson(httpResponse.getStatusLine().getStatusCode());
            }
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally{
            // 关闭连接
            try {
                if (closeableHttpClient!=null)
                    closeableHttpClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    /**
     * 调用HTTPS接口的POST方法
     * @param url
     * @param charset 默认UTF-8
     * @param params
     * @return 200时返回接口返回值，否则返回"{\"errorCode\":\"错误码\"}"
     * @throws RuntimeException
     */
    public static ServiceResponse HttpsPost(String url, String charset,
                                   Map<String,Object> params,Map<String,String> headerMap,String token) throws RuntimeException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = createHttpsClient();
            // 建立HttpPost对象
            HttpPost httppost = new HttpPost(url);
            if(token!=null&&!"".equals(token)){
                httppost.setHeader(	"Authorization",token);

            }
            // 配置要 POST 的数据begin
            List<NameValuePair> nvp = new ArrayList<NameValuePair>();
            for (Map.Entry<String, Object> e: params.entrySet())
                nvp.add(new BasicNameValuePair(e.getKey(), e.getValue()+""));
            httppost.setEntity(new UrlEncodedFormEntity(nvp,charset));
            if(headerMap !=null && headerMap.size()>0){
                for(Map.Entry<String,String> e:headerMap.entrySet())
                    httppost.setHeader(e.getKey(),e.getValue());
            }
            // 发送Post,并返回一个HttpResponse对象
            HttpResponse httpResponse = closeableHttpClient.execute(httppost);
            HttpEntity httpEntity = httpResponse.getEntity();

            // 如果状态码为200,就是正常返回
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 得到返回的字符串
                return JSONObject.parseObject(EntityUtils.toString(httpEntity),ServiceResponse.class);
                // 如果是下载文件,可以用response.getEntity().getContent()返回InputStream
            } else {
                return getErrorCodeJson(httpResponse.getStatusLine().getStatusCode());
            }
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally{
            // 关闭连接
            try {
                if (closeableHttpClient!=null)
                    closeableHttpClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    /**
     * 调用HTTPS接口的POST方法
     * @param url
     * @param charset 默认UTF-8
     * @param params
     * @return 200时返回接口返回值，否则返回"{\"errorCode\":\"错误码\"}"
     * @throws RuntimeException
     */
    public static ServiceResponse HttpsPostJson(String url, String charset,JSONObject params,Map<String,String> headerMap,String token) throws RuntimeException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = createHttpsClient();
            // 建立HttpPost对象
            HttpPost httppost = new HttpPost(url);
            if(httppost!=null&&!"".equals(httppost)){
                httppost.setHeader("Authorization",token);

            }
            // 配置要 POST 的数据begin
            StringEntity stringEntity = new StringEntity(params.toJSONString(),charset);
            httppost.setEntity(stringEntity);

            if(headerMap !=null && headerMap.size()>0){
                for(Map.Entry<String,String> e:headerMap.entrySet())
                    httppost.setHeader(e.getKey(),e.getValue());
            }
            // 发送Post,并返回一个HttpResponse对象
            HttpResponse httpResponse = closeableHttpClient.execute(httppost);
            HttpEntity httpEntity = httpResponse.getEntity();
            // 如果状态码为200,就是正常返回
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 得到返回的字符串
                return JSONObject.parseObject(EntityUtils.toString(httpEntity),ServiceResponse.class);
                // 如果是下载文件,可以用response.getEntity().getContent()返回InputStream
            } else {
                return getErrorCodeJson(httpResponse.getStatusLine().getStatusCode());
            }
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally{
            // 关闭连接
            try {
                if (closeableHttpClient!=null)
                    closeableHttpClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 调用HTTPS接口的POST方法
     * @param url
     * @return 200时返回接口返回值，否则返回"{\"errorCode\":\"错误码\"}"
     * @throws RuntimeException
     */
    public static ServiceResponse HttpsGet(String url, Map<String,String> headerMap) throws RuntimeException {
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = createHttpsClient();
            // 建立HttpPost对象
            HttpGet httpGet = new HttpGet(url);
            if(headerMap !=null && headerMap.size()>0){
                for(Map.Entry<String,String> e:headerMap.entrySet())
                    httpGet.setHeader(e.getKey(),e.getValue());
            }
            // 发送Post,并返回一个HttpResponse对象
            HttpResponse httpResponse = closeableHttpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            // 如果状态码为200,就是正常返回
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 得到返回的字符串
                return JSONObject.parseObject(EntityUtils.toString(httpEntity),ServiceResponse.class);
                // 如果是下载文件,可以用response.getEntity().getContent()返回InputStream
            } else {
                return getErrorCodeJson(httpResponse.getStatusLine().getStatusCode());
            }
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally{
            // 关闭连接
            try {
                if (closeableHttpClient!=null)
                    closeableHttpClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static CloseableHttpClient createHttpsClient() throws Exception {
        X509TrustManager x509mgr = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] xcs, String string) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] xcs, String string) {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[] { x509mgr }, new java.security.SecureRandom());
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

    /**
     * TODO
     * @param statusCode
     * @return
     * String
     */
    private static ServiceResponse getErrorCodeJson(int statusCode) {
        return ServiceResponseHandle.failed(statusCode+"");
    }
}
